/*
 * Copyright 2008-2009 Nobject.org, All Rights Reserved.
 * 
 * This software is licensed under LGPL license.
 * See terms of license at gnu.org.
 * 
 * For more information,visit:
 * 
 * http://www.nobject.org
 */
package org.nobject.common.code.model.java;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Class Model class
 * 
 * @author bianrongjun
 * @version 1.0
 */
public class ClassModel {

	/** 包名 */
	private String classPackage = null;
	/** 类名 */
	private String className = "";
	/** 类注释 */
	private String classComment = null;
	/** 类作者 */
	private String classCommentAuthor = null;
	/** 类版本 */
	private String classCommentVersion = null;
	/** 类头部生声明 */
	private String classCommentHeader = null;
	/** 方法 */
	private Map<String, MethodModel> methods = new LinkedHashMap<String, MethodModel>();
	/** 成员变量 */
	private Map<String, VariableModel> fields = new LinkedHashMap<String, VariableModel>();
	/** 父类 */
	private ClassModel parentClass = null;
	/** 接口 */
	private Map<String, InterfaceModel> interfaces = null;
	/** IMPORTS */
	private List imports=new LinkedList();
	/** staticImports */
	private List<String> staticImports=new LinkedList();
	/** 注解 */
	private List<AnnotationModel> annotations=new LinkedList();
	/** codeIndent */
	private boolean codeIndent=false;
	
	/**
	 * 构造函数 
	 */
	public ClassModel() {}

	/**
	 * 构造函数 
	 * @param className
	 */
	public ClassModel(String className) {
		this.className = className;
	}

	/**
	 * 构造函数 
	 * @param className
	 * @param classPackage
	 */
	public ClassModel(String className, String classPackage) {
		this.classPackage = classPackage;
		this.className = className;
	}

	/** 
	 * 添加接口
	 * @param interfaze 接口
	 *  */
	public void addInterface(InterfaceModel interfaze) {
		if (this.interfaces == null)
			this.interfaces = new LinkedHashMap();
		this.interfaces.put(interfaze.getInterfaceName(), interfaze);
	}

	/** addMethod */
	public void addMethod(MethodModel method) {
		List params = method.getParams();
		String key = "";
		for (Iterator iterator = params.iterator(); iterator.hasNext();) {
			ParamModel param = (ParamModel) iterator.next();
			key += (param.getParamType() + " " + param.getParamName());
			if (iterator.hasNext()) {
				key += ",";
			}
		}
		this.methods.put(method.getMethodName() + "(" + (key.equals("") ? "" : key) + ")", method);
	}

	/** addVariable */
	public void addVariable(VariableModel variable) {
		fields.put(variable.getVariableName(), variable);
	}

	/** addImport */
	public void addImport(String classfullName){
		this.imports.add(classfullName);
	}
	
	/** 
	 * addStaticImport
	 * @param importName
	 */
	public void addStaticImport(String importName){
		this.staticImports.add(importName);
	}
	
	/** getClassPackage */
	public String getClassPackage() {
		return classPackage;
	}

	/** setClassPackage */
	public void setClassPackage(String classPackage) {
		this.classPackage = classPackage;
	}

	/** setClassName */
	public void setClassName(String className) {
		this.className = className;
	}

	/** getClassComment */
	public String getClassComment() {
		return classComment;
	}

	/** setClassComment */
	public void setClassComment(String classComment) {
		this.classComment = classComment;
	}

	/** getClassName */
	public String getClassName() {
		return className;
	}

	/** getClassCommentAuthor */
	public String getClassCommentAuthor() {
		return classCommentAuthor;
	}

	/** 
	 * setClassCommentAuthor
	 * @param classCommentAuthor
	 */
	public void setClassCommentAuthor(String classCommentAuthor) {
		this.classCommentAuthor = classCommentAuthor;
	}

	/**
	 * Get Class Comment Version
	 * 
	 * @return
	 */
	public String getClassCommentVersion() {
		return classCommentVersion;
	}

	/**
	 * Set Class Comment Version
	 * 
	 * @param classCommentVersion
	 */
	public void setClassCommentVersion(String classCommentVersion) {
		this.classCommentVersion = classCommentVersion;
	}

	/**
	 * Get Class Comment Header
	 * 
	 * @return
	 */
	public String getClassCommentHeader() {
		return classCommentHeader;
	}

	/**
	 * Set Class Comment Header
	 * 
	 * @param classCommentHeader
	 */
	public void setClassCommentHeader(String classCommentHeader) {
		this.classCommentHeader = classCommentHeader;
	}

	/**
	 * Get Parent Class
	 * 
	 * @return
	 */
	public ClassModel getParentClass() {
		return parentClass;
	}

	/**
	 * Set Parent Class
	 * 
	 * @param parentClass
	 */
	public void setParentClass(ClassModel parentClass) {
		this.parentClass = parentClass;
	}

	
	
	/** getClassAnnnotationClass */
	public List getAnnnotations() {
		return annotations;
	}

	/** setClassAnnnotationClass */
	public void addAnnnotation(AnnotationModel annotationModel) {
		this.annotations.add(annotationModel);
	}

	/** isCodeIndent */
	public boolean isCodeIndent() {
		return codeIndent;
	}

	/** setCodeIndent */
	public void setCodeIndent(boolean codeIndent) {
		this.codeIndent = codeIndent;
	}

	/**
	 * Check
	 * 
	 * @return
	 */
	private boolean check() {
		if (this.className != null && !this.className.equals("")) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 生成Class内容
	 * 
	 * @return
	 */
	public String generateClassString() {
		if (!check()) {
			System.err.println("类名不能为空!");
			return null;
		}
		StringBuffer sb = new StringBuffer();

		if (this.classCommentHeader != null && !this.classCommentHeader.equals("")) {
			sb.append("/*\n");
			sb.append(" * @(#) " + this.className + ".java" + "\n");
			sb.append(" * " + classCommentHeader + "\n");
			sb.append(" */\n\n");
		}

		if (this.classPackage != null) {
			sb.append("package " + this.classPackage + ";\n");
		}

		for (String imp : this.staticImports) {
			sb.append("import static "+imp+";");
			sb.append("\n");
		}
		
		for (Iterator iterator = this.imports.iterator(); iterator.hasNext();) {
			String imp = (String) iterator.next();
			sb.append("import "+imp+";");
			sb.append("\n");
		}
		
		sb.append("\n/**\n");
		sb.append(" * " + ((this.classComment != null) ? this.classComment : this.className) + "\n");
		if (this.classCommentAuthor != null)
			sb.append(" * @author " + this.classCommentAuthor + "\n");
		if (this.classCommentVersion != null)
			sb.append(" * @version " + this.classCommentVersion + "\n");
		sb.append(" */\n");
		
		if(this.annotations.size()>0){
			for(AnnotationModel annotationModel:this.annotations){
				sb.append(annotationModel.toString()+"\n");
			}
		}
		
		sb.append("public class " + this.className);
		
		if(this.parentClass!=null){
			sb.append(" extends "+this.parentClass.getClassName());
		}
		
		if(this.interfaces!=null){
			sb.append(" implements ");
			for (Iterator iterator = interfaces.keySet().iterator(); iterator.hasNext();) {
				String key = (String) iterator.next();
				InterfaceModel interfaz=(InterfaceModel)interfaces.get(key);
				sb.append(interfaz.getInterfaceName());
				if(iterator.hasNext()){
					sb.append(",");
				}
			}
		}
		
		sb.append("{\n");

		for (Iterator iterator = fields.keySet().iterator(); iterator.hasNext();) {
			String key = (String) iterator.next();
			VariableModel variable = (VariableModel) fields.get(key);
			if(!this.codeIndent) sb.append("\n");
			sb.append(variable.generateVariableString());
			if (variable.ifSet()) {
				this.addMethod(MethodModel.generateSetMethod(new ParamModel(variable)));
			}
			
			if (variable.ifGet()) {
				this.addMethod(MethodModel.generateGetMethod(new ParamModel(variable)));
			}
		}

		for (Iterator iterator = methods.keySet().iterator(); iterator.hasNext();) {
			String key = (String) iterator.next();
			MethodModel method = (MethodModel) methods.get(key);
			if(!this.codeIndent) sb.append("\n");
			sb.append(method.generateMethodString());
		}

		sb.append("\n");

		sb.append("\n");
		sb.append("}");
		return sb.toString();
	}


}
